package com.priox.sigar.jsf;

import com.mm.support.domain.TipoUsuario;
import com.mm.support.mapper.DTOMapperService;
import com.priox.sigar.application.cuentacontable.RegistroCuentaContableApp;
import com.priox.sigar.application.mappers.AgrupacionMapper;
import com.priox.sigar.application.mappers.CuentaContableMapper;
import com.priox.sigar.client.dto.AgrupacionDTO;
import com.priox.sigar.client.dto.CuentaContableDTO;
import com.priox.sigar.client.flt.CuentaContableFlt;
import com.priox.sigar.domain.model.CuentaContable;
import com.priox.sigar.domain.model.constantes.PathConstant;
import com.priox.sigar.enums.ActivoInactivo;
import com.priox.sigar.enums.TipoCuenta;
import com.priox.sigar.enums.TipoCuentaOperacion;
import com.priox.sigar.enums.TipoVisible;
import com.priox.sigar.jsf.util.FindCrudBeanBase;
import com.priox.sigar.server.infrastructure.persistence.exception.ApplicationException;
import com.priox.sigar.util.FileUtil;
import com.priox.sigar.util.TimeObserver;
import org.apache.commons.lang3.StringUtils;
import org.primefaces.component.inputtext.InputText;
import org.primefaces.event.CloseEvent;
import org.primefaces.event.FileUploadEvent;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.batch.core.ExitStatus;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.JobParametersBuilder;
import org.springframework.batch.core.launch.JobLauncher;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.event.ActionEvent;
import javax.faces.event.AjaxBehaviorEvent;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@ManagedBean
@Scope("session")
@Component
public class MaestroCuentaContableJsfBean extends FindCrudBeanBase {


    private static final Logger LOG = LoggerFactory.getLogger(MaestroCuentaContableJsfBean.class);

    CuentaContableFlt filtroBusqueda;

    CuentaContableDTO nuevoRegistro;
    List<CuentaContableDTO> registros = new ArrayList<CuentaContableDTO>();
    List<AgrupacionDTO> cmbAgrupacion = new ArrayList<AgrupacionDTO>();



    @Autowired
    CuentaContableMapper cuentaContableMapper;

    @Autowired
    AgrupacionMapper agrupacionMapper;

    @Autowired
    DTOMapperService mapperService;

    @Autowired
    RegistroCuentaContableApp registroCuentaContableApp;

    @Autowired
    @Qualifier("jobCuentaContable")
    private Job jobCuentaContable;

    @Autowired
    private JobLauncher jobLauncher;

    @PostConstruct
    public void init() {
        filtroBusqueda = new CuentaContableFlt();
        filtroBusqueda.setOpcion(TipoVisible.VISIBLE);
        nuevoRegistro = new CuentaContableDTO();
        findRegistros();
    }

    @Override
    public void onShowEditDialog(ActionEvent actionEvent) {
        setUpdateMode(true);
        setPersistMode(true);
        InputText inputText = (InputText)findComponent("inputCodigo");
        inputText.setDisabled(true);
    }

    String archivoCarga;



    public void onFileUpload(FileUploadEvent event) {
        SimpleDateFormat sdf = new SimpleDateFormat("ddMMyyyy-kkmmss");
        String newFileName = "CUENTA_CONTABLE_" + sdf.format(new Date()) + ".csv";
        try {
            FileUtil.copyFile(event.getFile().getFileName(), event.getFile().getInputstream(), newFileName);

        } catch (IOException e) {
            throw new ApplicationException("Problemas al copiar el archivo:" + event.getFile().getFileName() + " a la ruta:" + PathConstant.DIR_TMP, e);
        }
        archivoCarga = newFileName;

    }

    public void procesar(ActionEvent actionEvent) {

        if(StringUtils.isBlank(archivoCarga)){
            throw new ApplicationException("El archivo no a sido cargado");
        }

        String archivo = PathConstant.DIR_TMP + File.separator + archivoCarga;
        JobParametersBuilder jpBuilder = new JobParametersBuilder()
                .addString("input.file.name", archivo);
        JobExecution execution = null;
        try {
            TimeObserver timeObserver = new TimeObserver("Lectura y escritura de acreedores");
            timeObserver.empezar();
            TimeObserver toBatch = new TimeObserver("Copiar a BD");
            toBatch.empezar();
            registroCuentaContableApp.deleteAll();
            execution = jobLauncher.run(jobCuentaContable, jpBuilder.toJobParameters());
            toBatch.terminar();
            LOG.debug(toBatch.mostrarMsg());
            if (ExitStatus.COMPLETED.equals(execution.getExitStatus())) {
                TimeObserver toSP = new TimeObserver("Copiar a BD");
                toSP.empezar();
                cuentaContableMapper.executeUpdate();
                toSP.terminar();
                LOG.debug(toSP.mostrarMsg());
                findRegistros();
            }
            timeObserver.terminar();
            LOG.debug(timeObserver.mostrarMsg());
        } catch (Exception e) {
            throw new ApplicationException("Problemas al procesar el archivo batch", e);
        }


    }


    /*Métodos de herencia*/

    @Override
    public void setCursorTableNull() {
        //To change body of implemented methods use File | Settings | File Templates.
    }

    @Override
    public void onNewRecord(ActionEvent actionEvent) {
        //To change body of implemented methods use File | Settings | File Templates.
        nuevoRegistro = new CuentaContableDTO();
        nuevoRegistro.setEstado(ActivoInactivo.ACTIVO);
    }

    @Override
    public void onFind(ActionEvent actionEvent) {
        findRegistros();
    }

    public void findRegistros() {
        filtroBusqueda.setUsuarioId(getUser().getUsuarioId());
        registros = cuentaContableMapper.findByFilter(filtroBusqueda);
        if (registros.size() == 0) {
            addMessage(noRecordFoundMsg, FacesMessage.SEVERITY_INFO);
        }
    }

    @Override
    public void onClean(ActionEvent actionEvent) {
        registros = new ArrayList<CuentaContableDTO>();

        nuevoRegistro = new CuentaContableDTO();
        filtroBusqueda = new CuentaContableFlt();
        filtroBusqueda.setOpcion(TipoVisible.VISIBLE);
    }

    @Override
    public void onPersist(ActionEvent actionEvent) {
        CuentaContable cuentaContable =mapperService.map(nuevoRegistro,CuentaContable.class);
        registroCuentaContableApp.save(cuentaContable, updateMode);
        InputText inputText = (InputText)findComponent("inputCodigo");
        inputText.setDisabled(false);
    }

    public TipoCuenta[] getAllTipoCuenta(){
        return TipoCuenta.valuesListAgrupacion();
    }

    public ActivoInactivo[] getAllEstado(){
        return ActivoInactivo.values();
    }

    public TipoVisible[] getAllOpcion(){
        return TipoVisible.values();
    }

    public boolean isAdministrador() {
        return TipoUsuario.ADMINISTRADOR.equals(getUser().getTipoUsuario());
    }

    public void onSelectTipoCuenta(AjaxBehaviorEvent actionEvent) {
        if(filtroBusqueda.getTipoCuentaBusqueda()==null){
            cmbAgrupacion=new ArrayList<AgrupacionDTO>();
            return;
        }

        AgrupacionDTO agrupacionDTO = new AgrupacionDTO();
        agrupacionDTO.setUsuarioId(getUser().getUsuarioId());
        agrupacionDTO.setTipo(filtroBusqueda.getTipoCuentaBusqueda());
        cmbAgrupacion = agrupacionMapper.findByUsuarioId(agrupacionDTO);

    }

    @Override
    public void onDelete(ActionEvent actionEvent) {
        CuentaContable cuentaContable =mapperService.map(nuevoRegistro,CuentaContable.class);
        registroCuentaContableApp.delete(cuentaContable);
    }

    @Override
    protected void onDialogClose(CloseEvent event) {
        nuevoRegistro = new CuentaContableDTO();
    }




    /*Getters and Setters*/



    public CuentaContableFlt getFiltroBusqueda() {
        return filtroBusqueda;
    }

    public void setFiltroBusqueda(CuentaContableFlt filtroBusqueda) {
        this.filtroBusqueda = filtroBusqueda;
    }



    public CuentaContableDTO getNuevoRegistro() {
        if (nuevoRegistro == null) nuevoRegistro = new CuentaContableDTO();
        return nuevoRegistro;
    }

    public void setNuevoRegistro(CuentaContableDTO nuevoRegistro) {
        this.nuevoRegistro = nuevoRegistro;
    }

    public List<CuentaContableDTO> getRegistros() {
        return registros;
    }

    public void setRegistros(List<CuentaContableDTO> registros) {
        this.registros = registros;
    }

    public List<AgrupacionDTO> getCmbAgrupacion() {
        return cmbAgrupacion;
    }

    public void setCmbAgrupacion(List<AgrupacionDTO> cmbAgrupacion) {
        this.cmbAgrupacion = cmbAgrupacion;
    }

    public TipoCuentaOperacion[] getAllTipoOperacion() {
        return TipoCuentaOperacion.values();
    }

}
